package com.xzy.sms.web.system.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xzy.sms.web.system.entity.Config;
import com.xzy.sms.web.system.service.ConfigService;
import com.xzyframework.SpringContextHolder;
import com.xzyframework.utils.Exceptions;

/**
 * 配置项工具类
 * 
 * @author macong
 * @since 1.0
 * @version 2014-01-02 macong
 */
public class ConfigUtils {
    
    /** 日志打印器 */
    protected static Logger logger = LoggerFactory.getLogger(ConfigUtils.class);
    
    /** ConfigService */
    private static ConfigService configService;
    
    /** 引用对象Map，起到缓存的作用 ，key为id,value为config的cval */
    private static Map<String, String> cacheMap;
    
    /** 引用对象Map，起到缓存的作用 ，key为id,value为config的cval */
    private static Map<String, String> issuedCacheMap;
    
    // /** 这里可以设置默认的值 */
    // private static Map<String, String> defaultConfMap;
    
    static {
        cacheMap = new ConcurrentHashMap<String, String>();
        issuedCacheMap = new ConcurrentHashMap<String, String>();
        // 这里可以设置默认值，当从数据库中无法获取的时候则从默认值中获取,如果都获取不到，则返回null;
        // defaultConfMap.put("EIM.SERVER_URL", null);
    }
    
    //
    /**
     * 删除缓存
     */
    public static void delCache() {
        cacheMap.clear();
        issuedCacheMap.clear();
    }
    
    /**
     * 获取所有配置
     * 
     * @return xx
     */
    public static Map<String, String> getAllConfig() {
        return new HashMap<String, String>(cacheMap);
    }
    
    /**
     * 获取所有下发配置
     * 
     * @return xx
     */
    public static Map<String, String> getAllIssuedConfig() {
        return new HashMap<String, String>(issuedCacheMap);
    }
    
    /**
     * 根据ckey值和租户id获取字符串类型配置项
     * 
     * @param id ckey
     * @return val
     */
    public static String getConfig(String id) {
        String val = cacheMap.get(id);
        if (null == val) {
            Config conf = getConfigService().findConfig(id);
            if (null != conf) {
                val = conf.getCval();
                cacheMap.put(id, val);
                if (conf.isIssued()) {
                    issuedCacheMap.put(id, val);
                }
            } else {
                return getConfigService().getBussDefValue(id);// 取默认值
            }
        }
        return val;
    }
    
    /**
     * 根据ckey值获取字符串类型配置项
     * 
     * @param ckey ckey
     * @return val
     */
    public static String getStringConfig(String ckey) {
        return getConfig(ckey);
    }
    
    /**
     * 根据ckey值获取字符串类型配置项
     * 
     * @param ckey ckey
     * @return val
     */
    public static long getLongConfig(String ckey) {
        return Long.valueOf(getConfig(ckey));
    }
    
    /**
     * 根据ckey值获取字符串类型配置项
     * 
     * @param ckey ckey
     * @param defVal 默认值
     * @return val
     */
    public static String getStringConfig(String ckey, String defVal) {
        String val = getStringConfig(ckey);
        if (null == val) {
            val = defVal;
        }
        return val;
    }
    
    /**
     * 根据ckey值删除缓存中的值,在修改，删除的时候需要调用
     * 
     * @param ckey ckey
     */
    public static void removeCache(String ckey) {
        if (StringUtils.isEmpty(ckey)) {
            return;
        }
        cacheMap.remove(ckey);
        issuedCacheMap.remove(ckey);
    }
    
    /**
     * 根据ckey值获取布尔类型配置项
     * 
     * @param ckey ckey
     * @return val
     */
    public static Boolean getBooleanConfig(String ckey) {
        String configVal = getStringConfig(ckey);
        if (StringUtils.isEmpty(configVal)) {
            return null;
        }
        Boolean result = null;
        try {
            result = Boolean.parseBoolean(configVal);
        } catch (Exception e) {
            logger.error(Exceptions.getErrorMessageWithNestedException(e));
        }
        return result;
    }
    
    /**
     * 根据ckey值获取布尔类型配置项
     * 
     * @param ckey ckey
     * @param defValue defValue
     * @return val
     */
    public static Boolean getBooleanConfig(String ckey, boolean defValue) {
        Boolean objBoolean = getBooleanConfig(ckey);
        if (objBoolean == null) {
            return defValue;
        }
        return objBoolean;
    }
    
    /**
     * 根据ckey值获取Integer类型配置项
     * 
     * @param ckey ckey
     * @return val
     */
    public static Integer getIntegerConfig(String ckey) {
        String configVal = getStringConfig(ckey);
        if (StringUtils.isEmpty(configVal)) {
            return null;
        }
        Integer ival = null;
        try {
            ival = Integer.parseInt(configVal);
        } catch (NumberFormatException e) {
            logger.error(Exceptions.getErrorMessageWithNestedException(e));
        }
        return ival;
    }
    
    /**
     * 根据ckey值获取Map类型配置项
     * 
     * @param ckey ckey
     * @return val
     * @throws IOException 
     * @throws JsonMappingException 
     * @throws JsonParseException 
     */
    public static Map<?, ?> getMapConfig(String ckey) throws JsonParseException, JsonMappingException, IOException {
        String strConf = getStringConfig(ckey);
        if (StringUtils.isEmpty(strConf)) {
            return new HashMap<Object, Object>();
        }
        ObjectMapper mapper = new ObjectMapper();
		// 设置输出时包含属性的风格
		mapper.setSerializationInclusion(Include.NON_DEFAULT);
		// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
		mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		
		return mapper.readValue(strConf, Map.class);
    }
    
    /**
     * 获取 ConfigService实例
     * 
     * @return ConfigService
     */
    private static ConfigService getConfigService() {
        if (null == configService) {
            return SpringContextHolder.getBean(ConfigService.class);
        }
        return configService;
    }
    
    /**
     * 用正则表过滤的字符串，需要先转义特殊字符，否则会报异常
     * 
     * @param regex regex
     * @return 转义后的字符
     */
    public static String encodeRegexString(String regex) {
        String[] encodeArr = { "\\", "*", ".", "?", "+", "$", "^", "[", "]", "(", ")", "{", "}", "|", "/" };
        String rst = regex;
        for (String encode : encodeArr) {
            rst = StringUtils.replace(rst, encode, "\\" + encode);
        }
        return rst;
    }
}
